package org.shiro.demo.controller;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.security.KeyStore;
import java.util.List;
import java.util.regex.Pattern;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;

import org.springframework.core.io.Resource;

public class OutpushForIOS implements Runnable {

	private Resource path;
	private String password;

	private String host;

	public Resource getPath() {
		return path;
	}

	public void setPath(Resource path) {
		this.path = path;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	// public List<String> getAppleID() throws Exception {
	// return null;
	// }

	/**
	 * 组装apns规定的字节数组 使用增强型
	 *
	 * @param command
	 * @param deviceToken
	 * @param payload
	 * @return
	 * @throws IOException
	 */
	private static byte[] makebyte(byte command, String deviceToken, String payload, int identifer) {

		byte[] deviceTokenb = decodeHex(deviceToken);
		byte[] payloadBytes = null;
		ByteArrayOutputStream boas = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(boas);

		try {
			payloadBytes = payload.getBytes("UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return null;
		}

		try {
			dos.writeByte(command);
			dos.writeInt(identifer);// identifer
			dos.writeInt(Integer.MAX_VALUE);
			dos.writeShort(deviceTokenb.length);
			dos.write(deviceTokenb);
			dos.writeShort(payloadBytes.length);
			dos.write(payloadBytes);
			return boas.toByteArray();
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	private static final Pattern pattern = Pattern.compile("[ -]");

	private static byte[] decodeHex(String deviceToken) {
		String hex = pattern.matcher(deviceToken).replaceAll("");

		byte[] bts = new byte[hex.length() / 2];
		for (int i = 0; i < bts.length; i++) {
			bts[i] = (byte) (charval(hex.charAt(2 * i)) * 16 + charval(hex.charAt(2 * i + 1)));
		}
		return bts;
	}

	private static int charval(char a) {
		if ('0' <= a && a <= '9')
			return (a - '0');
		else if ('a' <= a && a <= 'f')
			return (a - 'a') + 10;
		else if ('A' <= a && a <= 'F')
			return (a - 'A') + 10;
		else {
			throw new RuntimeException("Invalid hex character: " + a);
		}
	}

	public void sendMessageForIOS(String message, long MessageID, List<String> tokens) throws Exception {

		//String keyPath = path;
		String ksType = "PKCS12";
		String ksPassword = password;
		String ksAlgorithm = "SunX509";

		// String deviceToken =
		// "429cf33983eb2cacfe9eb3739649e0ea2fc1c74f3177bd9ba0a24a1e41ac8e0c";
		// List<String> tokens = getAppleID();

		String serverHost = host;
		int serverPort = 2195;

		try {
			InputStream certInput = new FileInputStream(path.getFile());
			KeyStore keyStore = KeyStore.getInstance(ksType);
			keyStore.load(certInput, ksPassword.toCharArray());

			KeyManagerFactory kmf = KeyManagerFactory.getInstance(ksAlgorithm);
			kmf.init(keyStore, ksPassword.toCharArray());

			SSLContext sslContext = SSLContext.getInstance("TLS");
			sslContext.init(kmf.getKeyManagers(), null, null);

			SSLSocketFactory socketFactory = sslContext.getSocketFactory();

			Socket socket = socketFactory.createSocket(serverHost, serverPort);

			StringBuilder content = new StringBuilder();

			// String text = "jacabo";
			// System.out.println(message);

			content.append("{\"aps\":");
			content.append("{\"alert\":\"").append(message).append("\",\"badge\":1,\"sound\":\"").append("ping1").append("\"}");

			content.append(",\"cpn\":{\"MessageID\":").append(MessageID).append("}");
			content.append("}");

			for (String token : tokens) {
				try {
					byte[] msgByte = makebyte((byte) 1, token, content.toString(), 10000001);
					socket.getOutputStream().write(msgByte);
					socket.getOutputStream().flush();
				} catch (Exception e) {
					e.printStackTrace();// 一条报错 不会影响 其他的 发送

				}
			}
			socket.close();

			System.out.println("推送发送成功了");

		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("推送发送失败了");
		}

	}

	String message;
	long MessageID;
	List<String> tokens;

	public void setArgs(String message, long MessageID, List<String> tokens) {
		this.message = message;
		this.MessageID = MessageID;
		this.tokens = tokens;
	}

	@Override
	public void run() {
		try {
			sendMessageForIOS(message, MessageID, tokens);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/*
	 * public void sendMessageForIOS(String message,long MessageID) { try {
	 * String deviceToken =
	 * "429cf33983eb2cacfe9eb3739649e0ea2fc1c74f3177bd9ba0a24a1e41ac8e0c"; //
	 * 被推送的iphone应用程序标示符 PayLoad payLoad = new PayLoad();
	 * payLoad.addAlert(message); payLoad.addBadge(1);
	 * payLoad.addSound("default");
	 * 
	 * PushNotificationManager pushManager =
	 * PushNotificationManager.getInstance(); //记得删除
	 * pushManager.addDevice("iphone", deviceToken);
	 * 
	 * String host = "gateway.sandbox.push.apple.com"; // 测试用的苹果推送服务器 // String
	 * host="gateway.push.apple.com"; int port = 2195; //证书地址是D:/push.p12 String
	 * certificatePath = "D:/push.p12"; // 刚才在mac系统下导出的证书
	 * 
	 * String certificatePassword = "test";
	 * 
	 * pushManager.initializeConnection(host, port, certificatePath,
	 * certificatePassword, SSLConnectionHelper.KEYSTORE_TYPE_PKCS12);
	 * 
	 * // Send Push Device client = pushManager.getDevice("iphone");
	 * pushManager.sendNotification(client, payLoad); // 推送消息
	 * pushManager.stopConnection(); pushManager.removeDevice("iphone"); } catch
	 * (Exception e) { e.printStackTrace(); System.out.println("push faild!");
	 * return; } System.out.println("push succeed!"); }
	 */
}
